/*
 * To owl2 this template, choose Tools | Templates
 * and open the template in the editor.
 */

package xowl.interpreter.impl;

import xowl.utils.Values;
import xowl.interpreter.QuerySolution;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import xowl.interpreter.Hook;
import xowl.interpreter.XOWLException;
import xowl.lang.actions.QueryVariable;
import xowl.lang.actions.Select;
import xowl.lang.owl2.AnonymousIndividual;
import xowl.lang.owl2.DataAllValuesFrom;
import xowl.lang.owl2.DataComplementOf;
import xowl.lang.owl2.DataExactCardinality;
import xowl.lang.owl2.DataHasValue;
import xowl.lang.owl2.DataIntersectionOf;
import xowl.lang.owl2.DataMaxCardinality;
import xowl.lang.owl2.DataMinCardinality;
import xowl.lang.owl2.DataOneOf;
import xowl.lang.owl2.DataSomeValuesFrom;
import xowl.lang.owl2.DataUnionOf;
import xowl.lang.owl2.DatatypeRestriction;
import xowl.lang.owl2.IRI;
import xowl.lang.owl2.ObjectAllValuesFrom;
import xowl.lang.owl2.ObjectComplementOf;
import xowl.lang.owl2.ObjectExactCardinality;
import xowl.lang.owl2.ObjectHasSelf;
import xowl.lang.owl2.ObjectHasValue;
import xowl.lang.owl2.ObjectIntersectionOf;
import xowl.lang.owl2.ObjectInverseOf;
import xowl.lang.owl2.ObjectMaxCardinality;
import xowl.lang.owl2.ObjectMinCardinality;
import xowl.lang.owl2.ObjectOneOf;
import xowl.lang.owl2.ObjectSomeValuesFrom;
import xowl.lang.owl2.ObjectUnionOf;
import xowl.lang.runtime.Class;
import xowl.lang.runtime.DataProperty;
import xowl.lang.runtime.Datatype;
import xowl.lang.runtime.Entity;
import xowl.lang.runtime.Function;
import xowl.lang.runtime.Individual;
import xowl.lang.runtime.Literal;
import xowl.lang.runtime.ObjectProperty;
import xowl.lang.runtime.Value;

/**
 *
 * @author Laurent WOUTERS
 */
public class VMDynamicEvaluator extends AbstractEvaluator {
    private ThreadRunner thread;
    private Map<xowl.lang.runtime.Entity, Map<Integer, Hook>> hooks;

    public ThreadRunner getThread() { return thread; }

    public VMDynamicEvaluator(ThreadRunner thread) {
        this.thread = thread;
        this.hooks = new HashMap<xowl.lang.runtime.Entity, Map<Integer, Hook>>();
    }

    public void addHook(Hook hook) {
        Map<Integer, Hook> inner = hooks.get(hook.getEntity());
        if (inner == null) {
            inner = new HashMap<Integer, Hook>();
            hooks.put(hook.getEntity(), inner);
        }
        inner.put(hook.getParametersCount(), hook);
    }
    public void addHooks(Collection<Hook> hooks) {
        for (Hook hook : hooks)
            addHook(hook);
    }
    public void removeHook(Hook hook) {
        Map<Integer, Hook> inner = hooks.get(hook.getEntity());
        inner.remove(hook.getParametersCount());
        if (inner.isEmpty())
            hooks.remove(hook.getEntity());
    }
    public void removeHooks(Collection<Hook> hooks) {
        for (Hook hook : hooks)
            removeHook(hook);
    }
    
    private List<xowl.lang.runtime.Value> eval_Execution_GetValues(Evaluator parent, xowl.lang.actions.Execution expression) throws xowl.interpreter.XOWLException {
        List<xowl.lang.runtime.Value> values = null;
        if (expression.getValueSeq() != null)
            values = Sequences.toEvaluatedList(parent, expression.getValueSeq());
        else
            values = new ArrayList<xowl.lang.runtime.Value>();
        return values;
    }
    private xowl.lang.runtime.Value eval_Execution(Evaluator parent, xowl.lang.runtime.Closure closure, List<xowl.lang.runtime.Value> values) throws xowl.interpreter.XOWLException {
        ThreadContext head = new ThreadContext(closure);
        ThreadContext content = new ThreadContext(head);
        int i = 0;
        for (xowl.lang.actions.CodeVariable param : closure.getCloses().getAllBoundVars()) {
            content.assign(param, values.get(i));
            i++;
        }
        return thread.execute(closure, content);
    }
    @Override protected xowl.lang.runtime.Value eval_Invoke(Evaluator parent, xowl.lang.actions.Invoke expression) throws xowl.interpreter.XOWLException {
        xowl.lang.runtime.Function function = parent.evalFunction(parent, expression.getFunction());
        List<xowl.lang.runtime.Value> values = eval_Execution_GetValues(parent, expression);
        Map<Integer, Hook> inner = hooks.get(function.getInterpretationOf());
        if (inner != null) {
            Hook hook = inner.get(values.size());
            if (hook != null) {
                try {
                    Object[] objs = new Object[values.size()];
                    for (int i=0; i!=values.size(); i++)
                        objs[i] = parent.toJavaObject(values.get(i)).getObject();
                    Object value = hook.getCallback().execute(thread, objs);
                    if (!hook.hasReturn())
                        return null;
                    if (value != null) {
                        if (value instanceof xowl.lang.runtime.Value)
                            return (xowl.lang.runtime.Value)value;
                        xowl.lang.runtime.JavaObject result = new xowl.lang.runtime.JavaObject();
                        result.setObject(value);
                        result.setType(value.getClass());
                        return result;
                    } else
                        return null;
                } catch (xowl.interpreter.XOWLException ex) {
                    throw new XOWLException("Error while invoking hook: " + function.getInterpretationOf().getHasIRI().getHasValue());
                }
            }
        }
        for (xowl.lang.runtime.Closure closure : function.getAllDefinedAs()) {
            if (closure.getCloses().getAllBoundVars().size() == values.size())
                return eval_Execution(parent, closure, values);
        }
        throw new xowl.interpreter.XOWLException("Cannot find closure with " + values.size() + " parameters for function " + function.getInterpretationOf().getHasIRI().getHasValue());
    }
    @Override protected xowl.lang.runtime.Value eval_Execute(Evaluator parent, xowl.lang.actions.Execute expression) throws xowl.interpreter.XOWLException {
        xowl.lang.runtime.Closure closure = parent.evalClosure(parent, expression.getExecutes());
        List<xowl.lang.runtime.Value> values = eval_Execution_GetValues(parent, expression);
        return eval_Execution(parent, closure, values);
    }
    @Override protected xowl.lang.runtime.Value eval_Contains(Evaluator parent, xowl.lang.actions.Contains query) throws xowl.interpreter.XOWLException { throw getNotImplemented(); }
    @Override protected xowl.lang.runtime.Array eval_ValuesOf(Evaluator parent, xowl.lang.actions.ValuesOf query) throws xowl.interpreter.XOWLException { throw getNotImplemented(); }
    @Override protected xowl.lang.runtime.Value eval_ValueOf(Evaluator parent, xowl.lang.actions.ValueOf query) throws xowl.interpreter.XOWLException { throw getNotImplemented(); }
    @Override protected xowl.lang.runtime.Value eval_CodeVariable(Evaluator parent, xowl.lang.actions.CodeVariable expression) throws xowl.interpreter.XOWLException {
        return thread.evaluate(expression);
    }
    @Override protected xowl.lang.runtime.Value eval_ArrayElement(Evaluator parent, xowl.lang.actions.ArrayElement expression) throws xowl.interpreter.XOWLException {
        xowl.lang.runtime.Array original = parent.evalArray(parent, expression.getArray());
        Integer index = Integer.parseInt(parent.evalLiteral(parent, expression.getIndex()).getLexicalValue());
        for (xowl.lang.runtime.Element elem : original.getAllElements())
            if (elem.getIndex().equals(index))
                return elem.getValue();
        throw new xowl.interpreter.XOWLException("Out of bound index");
    }

    // Entity expressions
    @Override protected xowl.lang.runtime.Entity eval_NewEntity(Evaluator parent, xowl.lang.actions.NewEntity expression) throws xowl.interpreter.XOWLException {
        xowl.lang.runtime.Literal iri = parent.evalLiteral(parent, expression.getIri());
        return thread.getRepository().resolveEntity(iri.getLexicalValue());
    }
    @Override protected xowl.lang.runtime.Entity eval_EntityForIRI(Evaluator parent, xowl.lang.actions.EntityForIRI expression) throws xowl.interpreter.XOWLException {
        xowl.lang.runtime.Literal iri = parent.evalLiteral(parent, expression.getIri());
        return thread.getRepository().resolveEntity(iri.getLexicalValue());
    }






    // Individual expressions
    @Override protected xowl.lang.runtime.Individual eval_NewIndividual(Evaluator parent, xowl.lang.actions.NewIndividual expression) throws xowl.interpreter.XOWLException {
        xowl.lang.owl2.AnonymousIndividual individual = new xowl.lang.owl2.AnonymousIndividual();
        return individual;
    }



    // Literal expressions
    @Override protected xowl.lang.runtime.Literal eval_Plus(Evaluator parent, xowl.lang.actions.Plus expression) throws xowl.interpreter.XOWLException {
        xowl.lang.runtime.Literal ll = parent.evalLiteral(parent, expression.getLhsAs(null));
        xowl.lang.runtime.Literal lr = parent.evalLiteral(parent, expression.getRhsAs(null));
        return VMArithmetic.plus(thread.getRepository(), ll, lr);
    }
    @Override protected xowl.lang.runtime.Literal eval_Minus(Evaluator parent, xowl.lang.actions.Minus expression) throws xowl.interpreter.XOWLException {
        xowl.lang.runtime.Literal ll = parent.evalLiteral(parent, expression.getLhsAs(null));
        xowl.lang.runtime.Literal lr = parent.evalLiteral(parent, expression.getRhsAs(null));
        return VMArithmetic.minus(thread.getRepository(), ll, lr);
    }
    @Override protected xowl.lang.runtime.Literal eval_Mult(Evaluator parent, xowl.lang.actions.Mult expression) throws xowl.interpreter.XOWLException {
        xowl.lang.runtime.Literal ll = parent.evalLiteral(parent, expression.getLhsAs(null));
        xowl.lang.runtime.Literal lr = parent.evalLiteral(parent, expression.getRhsAs(null));
        return VMArithmetic.multiply(thread.getRepository(), ll, lr);
    }
    @Override protected xowl.lang.runtime.Literal eval_Divide(Evaluator parent, xowl.lang.actions.Divide expression) throws xowl.interpreter.XOWLException {
        xowl.lang.runtime.Literal ll = parent.evalLiteral(parent, expression.getLhsAs(null));
        xowl.lang.runtime.Literal lr = parent.evalLiteral(parent, expression.getRhsAs(null));
        return VMArithmetic.divide(thread.getRepository(), ll, lr);
    }
    @Override protected xowl.lang.runtime.Literal eval_Modulus(Evaluator parent, xowl.lang.actions.Modulus expression) throws xowl.interpreter.XOWLException {
        xowl.lang.runtime.Literal ll = parent.evalLiteral(parent, expression.getLhsAs(null));
        xowl.lang.runtime.Literal lr = parent.evalLiteral(parent, expression.getRhsAs(null));
        return VMArithmetic.modulus(thread.getRepository(), ll, lr);
    }
    @Override protected xowl.lang.runtime.Literal eval_BAnd(Evaluator parent, xowl.lang.actions.BAnd expression) throws xowl.interpreter.XOWLException {
        xowl.lang.runtime.Literal ll = parent.evalLiteral(parent, expression.getLhsAs(null));
        xowl.lang.runtime.Literal lr = parent.evalLiteral(parent, expression.getRhsAs(null));
        return VMArithmetic.and(thread.getRepository(), ll, lr);
    }
    @Override protected xowl.lang.runtime.Literal eval_BOr(Evaluator parent, xowl.lang.actions.BOr expression) throws xowl.interpreter.XOWLException {
        xowl.lang.runtime.Literal ll = parent.evalLiteral(parent, expression.getLhsAs(null));
        xowl.lang.runtime.Literal lr = parent.evalLiteral(parent, expression.getRhsAs(null));
        return VMArithmetic.or(thread.getRepository(), ll, lr);
    }
    @Override protected xowl.lang.runtime.Literal eval_BXOr(Evaluator parent, xowl.lang.actions.BXOr expression) throws xowl.interpreter.XOWLException {
        xowl.lang.runtime.Literal ll = parent.evalLiteral(parent, expression.getLhsAs(null));
        xowl.lang.runtime.Literal lr = parent.evalLiteral(parent, expression.getRhsAs(null));
        return VMArithmetic.xor(thread.getRepository(), ll, lr);
    }
    @Override protected xowl.lang.runtime.Literal eval_BNot(Evaluator parent, xowl.lang.actions.BNot expression) throws xowl.interpreter.XOWLException {
        xowl.lang.runtime.Literal ll = parent.evalLiteral(parent, expression.getExpressionAs(null));
        return VMArithmetic.not(thread.getRepository(), ll);
    }
    @Override protected xowl.lang.runtime.Literal eval_Equal(Evaluator parent, xowl.lang.actions.Equal expression) throws xowl.interpreter.XOWLException {
        xowl.lang.runtime.Value left = parent.evaluate(parent, expression.getLhsAs(null));
        xowl.lang.runtime.Value right = parent.evaluate(parent, expression.getRhsAs(null));
        return VMArithmetic.equals(thread.getRepository(), left, right);
    }
    @Override protected xowl.lang.runtime.Literal eval_Different(Evaluator parent, xowl.lang.actions.Different expression) throws xowl.interpreter.XOWLException {
        xowl.lang.runtime.Value left = parent.evaluate(parent, expression.getLhsAs(null));
        xowl.lang.runtime.Value right = parent.evaluate(parent, expression.getRhsAs(null));
        return VMArithmetic.different(thread.getRepository(), left, right);
    }
    @Override protected xowl.lang.runtime.Literal eval_Greater(Evaluator parent, xowl.lang.actions.Greater expression) throws xowl.interpreter.XOWLException {
        xowl.lang.runtime.Literal ll = parent.evalLiteral(parent, expression.getLhsAs(null));
        xowl.lang.runtime.Literal lr = parent.evalLiteral(parent, expression.getRhsAs(null));
        return VMArithmetic.greater(thread.getRepository(), ll, lr);
    }
    @Override protected xowl.lang.runtime.Literal eval_GreaterEqual(Evaluator parent, xowl.lang.actions.GreaterEqual expression) throws xowl.interpreter.XOWLException {
        xowl.lang.runtime.Literal ll = parent.evalLiteral(parent, expression.getLhsAs(null));
        xowl.lang.runtime.Literal lr = parent.evalLiteral(parent, expression.getRhsAs(null));
        return VMArithmetic.greaterEqual(thread.getRepository(), ll, lr);
    }
    @Override protected xowl.lang.runtime.Literal eval_Lesser(Evaluator parent, xowl.lang.actions.Lesser expression) throws xowl.interpreter.XOWLException {
        xowl.lang.runtime.Literal ll = parent.evalLiteral(parent, expression.getLhsAs(null));
        xowl.lang.runtime.Literal lr = parent.evalLiteral(parent, expression.getRhsAs(null));
        return VMArithmetic.lesser(thread.getRepository(), ll, lr);
    }
    @Override protected xowl.lang.runtime.Literal eval_LesserEqual(Evaluator parent, xowl.lang.actions.LesserEqual expression) throws xowl.interpreter.XOWLException {
        xowl.lang.runtime.Literal ll = parent.evalLiteral(parent, expression.getLhsAs(null));
        xowl.lang.runtime.Literal lr = parent.evalLiteral(parent, expression.getRhsAs(null));
        return VMArithmetic.lesserEqual(thread.getRepository(), ll, lr);
    }
    @Override protected xowl.lang.runtime.Literal eval_IRIOf(Evaluator parent, xowl.lang.actions.IRIOf expression) throws xowl.interpreter.XOWLException {
        xowl.lang.runtime.Entity entity = parent.evalEntity(parent, expression.getEntity());
        return VMArithmetic.iriOf(thread.getRepository(), entity);
    }
    @Override protected xowl.lang.runtime.Literal eval_LengthOf(Evaluator parent, xowl.lang.actions.LengthOf expression) throws xowl.interpreter.XOWLException {
        xowl.lang.runtime.Array array = parent.evalArray(parent, expression.getArray());
        return VMArithmetic.lengthOf(thread.getRepository(), array);
    }


    // Executable expressions
    @Override protected xowl.lang.runtime.Closure eval_Lambda(Evaluator parent, xowl.lang.actions.Lambda expression) throws xowl.interpreter.XOWLException {
        xowl.lang.runtime.Closure closure = new xowl.lang.runtime.Closure();
        xowl.lang.runtime.LexicalContext context = thread.contextGetBounds();
        closure.setCloses(expression);
        closure.setContext(context);
        return closure;
    }



    // Array expressions
    @Override protected xowl.lang.runtime.Array eval_Array(Evaluator parent, xowl.lang.actions.Array expression) throws xowl.interpreter.XOWLException {
        xowl.lang.runtime.Array result = new xowl.lang.runtime.Array();
        int i=0;
        for (xowl.lang.owl2.Expression exp : Sequences.toList(expression)) {
            xowl.lang.runtime.Element elem = new xowl.lang.runtime.Element();
            elem.setIndex(i);
            elem.setValue(parent.evaluate(parent, exp));
            result.addElements(elem);
            i++;
        }
        return result;
    }
    @Override protected xowl.lang.runtime.Array eval_Concat(Evaluator parent, xowl.lang.actions.Concat expression) throws xowl.interpreter.XOWLException {
        xowl.lang.runtime.Array result = new xowl.lang.runtime.Array();
        int i=0;
        for (xowl.lang.owl2.Expression exp : Sequences.toList(expression)) {
            xowl.lang.runtime.Value value = parent.evaluate(parent, exp);
            if (value instanceof xowl.lang.runtime.Array) {
                for (xowl.lang.runtime.Value val : Values.toList((xowl.lang.runtime.Array)value)) {
                    xowl.lang.runtime.Element elem = new xowl.lang.runtime.Element();
                    elem.setIndex(i);
                    elem.setValue(val);
                    result.addElements(elem);
                    i++;
                }
            } else {
                xowl.lang.runtime.Element elem = new xowl.lang.runtime.Element();
                elem.setIndex(i);
                elem.setValue(value);
                result.addElements(elem);
                i++;
            }
        }
        return result;
    }
    @Override protected xowl.lang.runtime.Array eval_Slice(Evaluator parent, xowl.lang.actions.Slice expression) throws xowl.interpreter.XOWLException {
        xowl.lang.runtime.Array original = parent.evalArray(parent, expression.getArray());
        Integer lower = Integer.parseInt(parent.evalLiteral(parent, expression.getLowerBound()).getLexicalValue());
        Integer upper = Integer.parseInt(parent.evalLiteral(parent, expression.getUpperBound()).getLexicalValue());
        List<xowl.lang.runtime.Value> values = Values.toList(original);
        xowl.lang.runtime.Array result = new xowl.lang.runtime.Array();
        int index = 0;
        for (int i=lower; i!=upper+1; i++) {
            xowl.lang.runtime.Element temp = new xowl.lang.runtime.Element();
            temp.setIndex(index);
            temp.setValue(values.get(i));
            result.addElements(temp);
            index++;
        }
        return result;
    }



    // Java Object Expressions
    private boolean eval_JavaInvokation_MatchMethod(java.lang.reflect.Method method, String name, List<java.lang.Class> types) {
        if (!method.getName().equals(name))
            return false;
        java.lang.Class[] expected = method.getParameterTypes();
        if (expected.length != types.size())
            return false;
        for (int i=0; i!=types.size(); i++) {
            JavaDatatype datatype = JavaDatatype.get(types.get(i));
            if (datatype == null) {
                if (!expected[i].isAssignableFrom(types.get(i)))
                    return false;
            } else if (!expected[i].isAssignableFrom(datatype.getJavaType())) {
                if (datatype.getJavaPrimitiveType() == null || !expected[i].isAssignableFrom(datatype.getJavaPrimitiveType()))
                    return false;
            }
        }
        return true;
    }
    @Override protected xowl.lang.runtime.JavaObject eval_JavaInvokation(Evaluator parent, xowl.lang.interop.JavaInvokation expression) throws xowl.interpreter.XOWLException {
        xowl.lang.runtime.JavaObject target = parent.evalJavaObject(parent, expression.getOn());
        String methodName = parent.evalLiteral(parent, expression.getMethod()).getLexicalValue();
        
        List<Object> values = new ArrayList<Object>();
        List<java.lang.Class> types = new ArrayList<java.lang.Class>();
        for (xowl.lang.owl2.Expression param : expression.getAllParams()) {
            xowl.lang.runtime.JavaObject javaObject = parent.toJavaObject(parent.evaluate(parent, param));
            if (javaObject != null) {
                values.add(javaObject.getObject());
                types.add(javaObject.getType());
            } else {
                values.add(null);
                types.add(java.lang.Object.class);
            }
        }
        
        
        java.lang.reflect.Method method = null;
        if (target == null) {
            // Static method call
            String[] parts = methodName.split("\\.");
            String className = methodName.substring(0, methodName.length() - parts[parts.length-1].length() - 1);
            String name = parts[parts.length-1];
            try {
                java.lang.Class c = java.lang.Class.forName(className);
                for (java.lang.reflect.Method m : c.getMethods()) {
                    if (eval_JavaInvokation_MatchMethod(m, name, types)) {
                        method = m;
                        break;
                    }
                }
            } catch (java.lang.Exception ex) {
                throw new xowl.interpreter.XOWLException("Cannot find static java method " + methodName);
            }
        } else {
            // Call on a java object
            for (java.lang.reflect.Method m : target.getType().getMethods()) {
                if (eval_JavaInvokation_MatchMethod(m, methodName, types)) {
                    method = m;
                    break;
                }
            }
        }
        if (method == null)
            throw new xowl.interpreter.XOWLException("Cannot find java method " + methodName);
        try {
            if (!method.isAccessible()) {
                method.setAccessible(true);
            }
            Object[] realParams = values.toArray();
            Object temp = null;
            if (target == null)
                temp = method.invoke(null, realParams);
            else
                temp = method.invoke(target.getObject(), realParams);
            if (temp != null) {
                xowl.lang.runtime.JavaObject result = new xowl.lang.runtime.JavaObject();
                result.setObject(temp);
                if (temp instanceof xowl.lang.runtime.Value)
                    result.setType(xowl.lang.runtime.Value.class);
                else
                    result.setType(temp.getClass());
                return result;
            } else
                return null;
        } catch (java.lang.Exception ex) {
            throw new xowl.interpreter.XOWLException("Cannot invoke java method " + methodName);
        }
    }
    
    @Override protected xowl.lang.runtime.JavaObject eval_NewObject(Evaluator parent, xowl.lang.interop.NewObject expression) throws xowl.interpreter.XOWLException {
        String classe = parent.evalLiteral(parent, expression.getClasse()).getLexicalValue();
        
        List<Object> values = new ArrayList<Object>();
        List<java.lang.Class> types = new ArrayList<java.lang.Class>();
        for (xowl.lang.owl2.Expression param : expression.getAllParams()) {
            xowl.lang.runtime.JavaObject javaObject = parent.toJavaObject(parent.evaluate(parent, param));
            if (javaObject != null) {
                values.add(javaObject.getObject());
                types.add(javaObject.getType());
            } else {
                values.add(null);
                types.add(java.lang.Object.class);
            }
        }
        
        try {
            java.lang.Class c = java.lang.Class.forName(classe);
            for (java.lang.reflect.Constructor constructor : c.getConstructors()) {
                java.lang.Class[] expected = constructor.getParameterTypes();
                if (expected.length != types.size())
                    continue;
                boolean compatible = true;
                for (int i=0; i!=types.size(); i++) {
                    if (!expected[i].isAssignableFrom(types.get(i))) {
                        compatible = false;
                        break;
                    }
                }
                if (compatible) {
                    Object[] realParams = values.toArray();
                    Object temp = constructor.newInstance(realParams);
                    xowl.lang.runtime.JavaObject result = new xowl.lang.runtime.JavaObject();
                    result.setObject(temp);
                    result.setType(c);
                    return result;
                }
            }
        } catch (java.lang.Exception ex) {
            throw new xowl.interpreter.XOWLException("Cannot instantiate java class " + classe);
        }
        return null;
    }
    @Override protected xowl.lang.runtime.JavaObject eval_ObjectField(Evaluator parent, xowl.lang.interop.ObjectField expression) throws xowl.interpreter.XOWLException {
        xowl.lang.runtime.JavaObject target = parent.evalJavaObject(parent, expression.getOn());
        xowl.lang.runtime.Literal field = parent.evalLiteral(parent, expression.getField());
        try {
            java.lang.reflect.Field f = target.getClass().getField(field.getLexicalValue());
            Object temp = f.get(target.getObject());
            if (temp == null)
                return null;
            xowl.lang.runtime.JavaObject result = new xowl.lang.runtime.JavaObject();
            result.setObject(temp);
            result.setType(f.getType());
            return result;
        } catch (java.lang.Exception ex) {
            throw new xowl.interpreter.XOWLException("Cannot access field " + field);
        }
    }
    @Override protected xowl.lang.runtime.JavaObject eval_StaticField(Evaluator parent, xowl.lang.interop.StaticField expression) throws xowl.interpreter.XOWLException {
        String classe = parent.evalLiteral(parent, expression.getClasse()).getLexicalValue();
        xowl.lang.runtime.Literal field = parent.evalLiteral(parent, expression.getField());
        try {
            java.lang.Class c = java.lang.Class.forName(classe);
            java.lang.reflect.Field f = c.getField(field.getLexicalValue());
            Object temp = f.get(null);
            if (temp == null)
                return null;
            xowl.lang.runtime.JavaObject result = new xowl.lang.runtime.JavaObject();
            result.setObject(temp);
            result.setType(f.getType());
            return result;
        } catch (java.lang.Exception ex) {
            throw new xowl.interpreter.XOWLException("Cannot access static field " + field);
        }
    }

    @Override protected Value eval_QueryVariable(Evaluator parent, QueryVariable expression) throws XOWLException { throw getNotImplemented(); }
    @Override protected Entity eval_Entity(Evaluator parent, IRI expression) throws XOWLException { throw getNotImplemented(); }
    @Override protected Class eval_Class(Evaluator parent, IRI expression) throws XOWLException { throw getNotImplemented(); }
    @Override protected Class eval_ObjectUnionOf(Evaluator parent, ObjectUnionOf expression) throws XOWLException { throw getNotImplemented(); }
    @Override protected Class eval_ObjectIntersectionOf(Evaluator parent, ObjectIntersectionOf expression) throws XOWLException { throw getNotImplemented(); }
    @Override protected Class eval_ObjectOneOf(Evaluator parent, ObjectOneOf expression) throws XOWLException { throw getNotImplemented(); }
    @Override protected Class eval_ObjectComplementOf(Evaluator parent, ObjectComplementOf expression) throws XOWLException { throw getNotImplemented(); }
    @Override protected Class eval_DataAllValuesFrom(Evaluator parent, DataAllValuesFrom expression) throws XOWLException { throw getNotImplemented(); }
    @Override protected Class eval_DataExactCardinality(Evaluator parent, DataExactCardinality expression) throws XOWLException { throw getNotImplemented(); }
    @Override protected Class eval_DataHasValue(Evaluator parent, DataHasValue expression) throws XOWLException { throw getNotImplemented(); }
    @Override protected Class eval_DataMaxCardinality(Evaluator parent, DataMaxCardinality expression) throws XOWLException { throw getNotImplemented(); }
    @Override protected Class eval_DataMinCardinality(Evaluator parent, DataMinCardinality expression) throws XOWLException { throw getNotImplemented(); }
    @Override protected Class eval_DataSomeValuesFrom(Evaluator parent, DataSomeValuesFrom expression) throws XOWLException { throw getNotImplemented(); }
    @Override protected Class eval_ObjectAllValuesFrom(Evaluator parent, ObjectAllValuesFrom expression) throws XOWLException { throw getNotImplemented(); }
    @Override protected Class eval_ObjectExactCardinality(Evaluator parent, ObjectExactCardinality expression) throws XOWLException { throw getNotImplemented(); }
    @Override protected Class eval_ObjectHasSelf(Evaluator parent, ObjectHasSelf expression) throws XOWLException { throw getNotImplemented(); }
    @Override protected Class eval_ObjectHasValue(Evaluator parent, ObjectHasValue expression) throws XOWLException { throw getNotImplemented(); }
    @Override protected Class eval_ObjectMaxCardinality(Evaluator parent, ObjectMaxCardinality expression) throws XOWLException { throw getNotImplemented(); }
    @Override protected Class eval_ObjectMinCardinality(Evaluator parent, ObjectMinCardinality expression) throws XOWLException { throw getNotImplemented(); }
    @Override protected Class eval_ObjectSomeValuesFrom(Evaluator parent, ObjectSomeValuesFrom expression) throws XOWLException { throw getNotImplemented(); }
    @Override protected ObjectProperty eval_ObjectProperty(Evaluator parent, IRI expression) throws XOWLException { throw getNotImplemented(); }
    @Override protected ObjectProperty eval_ObjectInverseOf(Evaluator parent, ObjectInverseOf expression) throws XOWLException { throw getNotImplemented(); }
    @Override protected DataProperty eval_DataProperty(Evaluator parent, IRI expression) throws XOWLException { throw getNotImplemented(); }
    @Override protected Datatype eval_Datatype(Evaluator parent, IRI expression) throws XOWLException { throw getNotImplemented(); }
    @Override protected Datatype eval_DataComplementOf(Evaluator parent, DataComplementOf expression) throws XOWLException { throw getNotImplemented(); }
    @Override protected Datatype eval_DataIntersectionOf(Evaluator parent, DataIntersectionOf expression) throws XOWLException { throw getNotImplemented(); }
    @Override protected Datatype eval_DataOneOf(Evaluator parent, DataOneOf expression) throws XOWLException { throw getNotImplemented(); }
    @Override protected Datatype eval_DatatypeRestriction(Evaluator parent, DatatypeRestriction expression) throws XOWLException { throw getNotImplemented(); }
    @Override protected Datatype eval_DataUnionOf(Evaluator parent, DataUnionOf expression) throws XOWLException { throw getNotImplemented(); }
    @Override protected Individual eval_NamedIndividual(Evaluator parent, IRI expression) throws XOWLException { throw getNotImplemented(); }
    @Override protected Individual eval_AnonymousIndividual(Evaluator parent, AnonymousIndividual expression) throws XOWLException { throw getNotImplemented(); }
    @Override protected Literal eval_Literal(Evaluator parent, xowl.lang.owl2.Literal expression) throws XOWLException { throw getNotImplemented(); }
    @Override protected Function eval_Function(Evaluator parent, IRI expression) throws XOWLException { throw getNotImplemented(); }

    @Override public boolean can(xowl.lang.owl2.Expression exp) {
        if (exp instanceof xowl.lang.actions.Query)
            return false;
        return Values.isDynamicExpression(exp);
    }
    @Override public boolean can(xowl.lang.actions.Query exp) { return false; }

    @Override public List<QuerySolution> select(Evaluator parent, Select query) throws XOWLException { throw getNotImplemented(); }
}
